/*
 *  objx(o).event("onSomething")
 *  Adds events to an object
 */

objx.requires("objx.is", "objx.event");

objx.fn.event = function() {

	// if no event name - throw exception
	if (arguments.length === 0 || !objx(arguments[0]).is("string", "something")) {
		objx.error("event", "You must provide an event name");
	}
	
	// get the event name
	var eventName = arguments[0],
		obj = this.obj();
	
	if (!this.is("something")) {
		objx.error("Cannot add events to objects of type " + this.type());
	}
	
	// add the events structure to the object
	obj.objx = obj.objx || {};
	obj.objx.event_listeners = obj.objx.event_listeners || {};
	obj.objx.event_listeners[eventName] = [];
	
	// add the lovely shortcut method
	obj[eventName] = (function(eName){
		
		// bind these
		var __eventName = eName;
		
		// return a function that will call the right event method
		return function(){
			
			// is the only argument a function?
			if (arguments.length == 1 && objx(arguments[0]).is("function")) {
			
				// add the listener
				this.listenFor[__eventName].apply(this, arguments);
				
			} else {
			
				// fire the event
				this.fire[__eventName].apply(this, arguments);
				
			}
			
			return this;
			
		};
		
	})(eventName);
	
	// add the fire item
	obj.fire = obj.fire || {};
	obj.fire[eventName] = objx.bind(function() { 

		// trigger each listener in the list
		objx(this.objx.event_listeners[eventName]).each(
		
			// bind the right context and arguments
			objx.bind(
			
				// the function to bind to
				function(args, item){
					return item.apply(this, args);
				},
				
				// 'this' is the object that is firing the event
				this,
				
				// these are any arguments specified
				arguments
			)
		);
		
	}, obj);
	
	// add the listenFor item
	obj.listenFor = obj.listenFor || {};
	obj.listenFor[eventName] = objx.bind(function(func) {
	
		// add the listener to the list
		this.objx.event_listeners[eventName].push(func);
		
	}, obj);
	
	// return this for chaining
	return this;
	
};

// shortcut reference object
objx.event = {};

objx.provides("objx.event");